import { FC, useEffect, useMemo, useState } from 'react';
import { AutoComplete, AutoCompleteProps } from 'antd';

import { getTempData } from '../_common/wrapXhr';
import { ApiConfig, DynamicObjectAny } from '@/typings';
import { getPathValue } from '@/biz-components/_common/valueUtil';

import template from 'es6-template-strings';
const TEMPLATE_REG_EXP = /\${[0-9.A-Za-z]*}/;

export interface BiZAutoCompleteProps extends AutoCompleteProps {
  api?: ApiConfig; //接口参数，包含（url:接口地址，params:发送的数据，一旦发送数据默认GET）
  valueTemplateKey?: string;
  labelTemplateKey?: string;
  remoteDataPath?: string[];
  onChange: (value: V, record?: DynamicObjectAny | DynamicObjectAny[]) => void;
  [key: string]: any;
}

const BiZAutoComplete: FC<BiZAutoCompleteProps> = ({
  editable,
  value,
  api,
  valueTemplateKey,
  labelTemplateKey,
  remoteDataPath,
  onChange,
  ...restProps
}) => {
  const [options, setOptions] = useState<AutoCompleteProps['options']>([]);

  const [caseLikeValue, setCaseLikeValue] = useState<string | undefined>();

  const { params, url, type } = api || {};

  const findRecord = (val: string): undefined | DynamicObjectAny => {
    return val ? options?.find((item) => item.changeValue === val) : {};
  };

  const triggerChange = (changedValue: any) => {
    const record = Array.isArray(changedValue)
      ? changedValue
          .map((val) => {
            return findRecord(val);
          })
          .filter((val) => val)
      : findRecord(changedValue);

    onChange?.(changedValue, record);
  };

  const transformData = (data: any): any[] => {
    return data.map((item: any) => {
      const { name, code } = item;

      const isLabelTemplateString = TEMPLATE_REG_EXP.test(labelTemplateKey || '');
      const isValueTemplateString = TEMPLATE_REG_EXP.test(valueTemplateKey || '');

      let newLabel = labelTemplateKey ? item[labelTemplateKey] : name;
      let newValue = valueTemplateKey ? item[valueTemplateKey] : code;

      if (isLabelTemplateString) {
        newLabel = template(labelTemplateKey, item);
      }

      if (isValueTemplateString) {
        newValue = template(valueTemplateKey, item);
      }

      return {
        ...item,
        label: newLabel,
        value: newLabel,
        changeValue: newValue,
      };
    });
  };

  const handleLikeSearch = (searchText: string) => {
    const caseLikeValue = searchText?.toLocaleUpperCase() || '';

    setCaseLikeValue(caseLikeValue);
  };

  const search = () => {
    getTempData({
      type,
      url,
      params,
    }).then((res) => {
      const remoteData = getPathValue<any[], any>(res, remoteDataPath);
      const newData = remoteData ? transformData(remoteData) : [];

      setOptions(newData);
    });
  };

  const handleChange = (val: string, opt: any) => {
    triggerChange(opt?.changeValue || val);
  };

  useEffect(() => {
    if (url && type) {
      search();
    } else {
      setOptions([]);
    }
  }, [type, url, params]);

  const displayValue = useMemo(() => {
    const { label } = options?.find((item) => item.changeValue === value) || {
      label: value,
    };
    return (label || '') as string | undefined;
  }, [value, options]);

  const handleDropdownVisibleChange = (open: boolean) => {
    if (!open) {
      setCaseLikeValue(undefined);
    }
  };

  return editable ? (
    <AutoComplete
      defaultActiveFirstOption={false}
      value={displayValue}
      {...restProps}
      onSearch={handleLikeSearch}
      filterOption={false}
      onChange={handleChange}
      onDropdownVisibleChange={handleDropdownVisibleChange}
      options={
        !caseLikeValue
          ? options
          : options?.filter((item) => {
              const { changeValue: optionValue, label } = item;
              return (
                optionValue?.toLocaleUpperCase().includes(caseLikeValue) ||
                (label as string)?.toLocaleUpperCase().includes(caseLikeValue)
              );
            }) || []
      }
    />
  ) : (
    <span> {value}</span>
  );
};

export default BiZAutoComplete;


